package com.bmob.lover.ui.activity

import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import androidx.activity.viewModels
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationListener
import com.bumptech.glide.Glide
import com.hjq.permissions.OnPermission
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.qmuiteam.qmui.arch.annotation.DefaultFirstFragment
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction
import com.theone.common.callback.OnKeyBackClickListener
import com.bmob.lover.app.ext.isSameLocation
import com.bmob.lover.app.util.CacheUtil
import com.bmob.lover.app.util.FestivalUtil
import com.bmob.lover.app.util.UpdateAppUtil
import com.bmob.lover.app.ext.getClipDataAndCheck
import com.bmob.lover.data.model.bean.UserLocation
import com.bmob.lover.data.model.enums.BackgroundType
import com.bmob.lover.data.room.AppDataBase
import com.bmob.lover.data.room.BackgroundDao
import com.bmob.lover.ui.fragment.MainFragment
import com.bmob.lover.viewmodel.request.*
import com.theone.common.constant.BundleConstant
import com.theone.common.ext.*
import com.theone.mvvm.base.activity.BaseFragmentActivity
import com.theone.mvvm.ext.qmui.showMsgDialog
import the.one.location.TheLocationManager
import java.util.*

@DefaultFirstFragment(MainFragment::class)
class IndexActivity : BaseFragmentActivity(), AMapLocationListener {

    /**
     *  定位逻辑
     *  1. 开启定位，得到用户当前的地理位置信息。
     *  2. 对比：先拿本地保存的，如果本地存在且和定位到的不是同一个，则保存至服务器，成功后再更新本地数据
     *           本地数据不存在，从网络获取当前用户最新的一条位置信息，如果位置不一致，则保存至服务器，成功后同样保存至本地
     *
     *  这样不会每次定位到了都保存，也能保存到每个时间下用户的位置信息，后期可以得到一条轨迹图
     *
     */

    /**
     * 用户地理位置数据请求
     */
    private val mLocationRequestVm: LocationRequestViewModel by viewModels()

    /**
     * 用户地理位置保存
     */
    private val mLocationSaveVm: LocationSaveViewModel by viewModels()

    /**
     * 定位到的地理位置
     */
    private var mLocation: AMapLocation? = null

    /**
     * 定位工具
     */
    private var mLocationUtil: TheLocationManager? = null

    /**
     *   防止定位失败，设置一个失败次数
     */
    private var mLocationTimes: Int = 0

    /**
     * 节日背景
     */
    private val mFestivalBgRequest: FestivalBgRequestViewModel by viewModels()

    private val mLogRequest: LogActionViewModel by viewModels()

    private val mFestivalDao: BackgroundDao by lazy {
        AppDataBase.INSTANCE.backgroundDao()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mLocationUtil = TheLocationManager.getInstance()?.init(this, this)
        requestPermission()
        createObserve()
    }

    /**
     * 请求权限
     */
    private fun requestPermission() {
        XXPermissions.with(this)
            .permission(Permission.MANAGE_EXTERNAL_STORAGE)
            .permission(Permission.READ_PHONE_STATE)
            .permission(Permission.Group.LOCATION)
            .constantRequest()
            .request(object : OnPermission {

                override fun hasPermission(granted: MutableList<String>?, all: Boolean) {
                    if (all) {
                        requestLocation()
                        UpdateAppUtil(this@IndexActivity, false).checkUpdate()
                        requestFestivalBg()
                    }
                }

                override fun noPermission(denied: MutableList<String>?, quick: Boolean) {
                    if (quick) {
                        showFailDialog(
                            "权限被禁止，请在设置里打开权限",
                            "打开权限"
                        ) {
                            XXPermissions.startPermissionActivity(this@IndexActivity, denied)
                        }
                    }
                }
            })
    }

    private fun createObserve() {
        mLocationRequestVm.getResponseLiveData()
            .observe(this, androidx.lifecycle.Observer {
                if (it.isNullOrEmpty()) {
                    // 没有获取到用户的地理位置记录，直接保存
                    mLocation?.let { location ->
                        mLocationSaveVm.save(location)
                    }
                } else {
                    // 如果存在，对比最后一次的地理位置是否相同，不同则保存
                    checkUserLocation(it[0], true)
                }
            })

        mLocationSaveVm.getObjectSuccessLiveDate()
            .observe(this, androidx.lifecycle.Observer {
                // 保存到本地
                CacheUtil.setUserLocation(mLocationSaveVm.mUserLocation.apply {
                    objectId = it.objectId
                    createdAt = it.createdAt
                    className = javaClass.simpleName
                })
                saveLog()
            })
        mFestivalBgRequest.getResponseLiveData().observe(this) {
            mFestivalDao.run {
                delete(BackgroundType.FESTIVAL)
                insert(it)
            }
        }
    }

    /**
     * 开始定位
     */
    private fun requestLocation() {
        mLocationUtil?.start()
    }

    /**
     * 请求节日壁纸
     */
    private fun requestFestivalBg() {
        mFestivalBgRequest.requestServer()
    }

    /**
     * 定位回调
     * @param aMapLocation AMapLocation
     */
    override fun onLocationChanged(aMapLocation: AMapLocation?) {
        // 停止定位
        mLocationUtil?.stop()
        if (null == aMapLocation || TextUtils.isEmpty(aMapLocation.city)) {
            if (mLocationTimes == 3) {
                mLocationTimes = 0
                showFailDialog(
                    "定位失败，请检查网络或者GPS是否打开。",
                    "重新定位"
                ) {
                    requestPermission()
                }
            } else {
                mLocationTimes++
                requestLocation()
            }
        } else {
            mLocation = aMapLocation
            // @TODO 先拿本地保存的用户位置信息做判断
            CacheUtil.getUserLocation().notNull({
                checkUserLocation(it)
            }, {
                mLocationRequestVm.requestServer()
            })
        }

    }

    /**
     * 检查用户的地理位置是否和上次记录的(本地或者服务器）一样
     * @param location 地理位置信息
     * @param isNet  数据是否从服务器获取的
     */
    private fun checkUserLocation(location: UserLocation?, isNet: Boolean = false) {
        // 如果存在，对比最后一次的地理位置是否相同，不同则保存至服务器
        mLocation?.let {
            if (location?.isSameLocation(it) == false) {
                mLocationSaveVm.save(it)
                // 地理位置不相同，等保存成功后再保存日志
                return
            } else if (isNet) {
                // 服务器拿到的拿来对比说明本地数据不存在，需要保存
                CacheUtil.setUserLocation(location)
            }
        }
        saveLog()
    }

    private fun saveLog() {
        mLogRequest.save("Enter")
    }

    private fun showFailDialog(
        tips: String,
        actionString: String,
        callback: (() -> Unit?)? = null
    ) {
        showMsgDialog(
            "提示",
            tips,
            rightAction = actionString,
            listener = QMUIDialogAction.ActionListener { dialog, index ->
                dialog.dismiss()
                if (index > 0)
                    callback?.invoke()
            },
            prop = QMUIDialogAction.ACTION_PROP_NEGATIVE
        ).run {
            setCanceledOnTouchOutside(false)
            setOnKeyListener(OnKeyBackClickListener())
        }
    }

    override fun onResume() {
        super.onResume()
        getClipDataAndCheck {
            startActivity(Intent(this, ShortVideoParseActivity::class.java).apply {
                putExtra(BundleConstant.DATA, it)
            })
        }
    }

    override fun onDestroy() {
        mLocationUtil?.release()
        super.onDestroy()
    }

}